package com.mxpio.erp.hr.service.impl;

import cn.hutool.core.date.DateUtil;
import com.mxpio.erp.common.enums.CommonEnums;
import com.mxpio.erp.common.enums.HrEnums;
import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.hr.entity.AttendanceMonth;
import com.mxpio.erp.common.hr.entity.AttendanceRecorder;
import com.mxpio.erp.common.hr.service.AttendanceMonthService;
import com.mxpio.erp.common.oa.entity.OaLeave;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.policy.impl.CrudType;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class AttendanceMonthServiceImpl extends BaseServiceImpl<AttendanceMonth> implements AttendanceMonthService {

    @Override
    @Transactional
    public Result<?> calculateSummary(String yearMonth) {
        try {
            DateUtil.parse(yearMonth, "yyyy-MM");
        } catch (Exception e) {
            return Result.error("输入的日期格式不正确(yyyy-MM，例：2025-01)-》"+yearMonth);
        }
        String[] split = yearMonth.split("-");
        Integer year = Integer.parseInt(split[0]);
        Integer month = Integer.parseInt(split[1]);
        Calendar startTime = Calendar.getInstance();
        Calendar endTime = Calendar.getInstance();
        startTime.set(year, month-1, 1);
        endTime.set(year, month-1, startTime.getActualMaximum(Calendar.DAY_OF_MONTH));
        //处理历史数据
        String startDate = DateUtil.formatDate(startTime.getTime());
        String endDate = DateUtil.formatDate(endTime.getTime());
        List<AttendanceRecorder> recorders = JpaUtil.linq(AttendanceRecorder.class).between("date", startDate, endDate).list();
        if (recorders.isEmpty()){
            return Result.error("未获取到该月份用户考勤打卡记录，请先同步打卡数据！");
        }
        Map<String, List<AttendanceRecorder>> recorderGroupByUserMap = recorders.stream().collect(Collectors.groupingBy(AttendanceRecorder::getUsername));
        List<AttendanceMonth> attendanceMonths = new ArrayList<>();
        for(String username:recorderGroupByUserMap.keySet()){
            List<AttendanceRecorder> perUserRecorderList = recorderGroupByUserMap.get(username);
            AttendanceMonth attendanceMonth = JpaUtil.linq(AttendanceMonth.class).equal("yearMonth", yearMonth).equal("username", username).findOne();
            if (attendanceMonth == null){
                attendanceMonth = new AttendanceMonth();
                attendanceMonth.setUsername(username);
                attendanceMonth.setYearMonth(yearMonth);
                attendanceMonth.setPerformanceScore(BigDecimal.ONE);//默认1分
                AttendanceRecorder attendanceRecorder = perUserRecorderList.get(0);
                attendanceMonth.setNickname(attendanceRecorder.getNickname());//从日报数据中获取，防止用户信息调整前后不一致
                attendanceMonth.setDeptCode(attendanceRecorder.getDeptCode());
                attendanceMonth.setCrudType(CrudType.SAVE);
            }else{
                attendanceMonth.setCrudType(CrudType.UPDATE);
            }
            //统计加班工时
            BigDecimal workDayHours = perUserRecorderList.stream().filter(per -> StringUtils.equals(HrEnums.AttendanceCalendarDataType.WORK.getCode(), per.getDateType())).map(AttendanceRecorder::getWorkingHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            attendanceMonth.setOnePointFiveHours(workDayHours);
            BigDecimal weekendDayHours = perUserRecorderList.stream().filter(per -> StringUtils.equals(HrEnums.AttendanceCalendarDataType.WEEKEND.getCode(), per.getDateType())).map(AttendanceRecorder::getWorkingHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            attendanceMonth.setDoubleHours(weekendDayHours);
            BigDecimal holidayHours = perUserRecorderList.stream().filter(per -> StringUtils.equals(HrEnums.AttendanceCalendarDataType.HOLIDAY.getCode(), per.getDateType())).map(AttendanceRecorder::getWorkingHours)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            attendanceMonth.setThriceHours(holidayHours);

            //判断是否有请假时间在当月范围内的请假单
            Long oaleaveCnt = JpaUtil.linq(OaLeave.class).equal("employeeId", username)
                    .equal("bpmnStatus", OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())
                    .greaterThanOrEqualTo("leaveStartTime", startTime.getTime())
                    .lessThanOrEqualTo("leaveEndTime", endTime.getTime()).count();
            attendanceMonth.setFullFlag(oaleaveCnt>0? CommonEnums.YesNo.YES.getCode() : CommonEnums.YesNo.NO.getCode());

            //仅统计工作日出勤的天数，周末和节假日已按加班工时口径来计算加班费用
            attendanceMonth.setAttendanceDays(new BigDecimal(perUserRecorderList.stream().filter(per -> StringUtils.equals(HrEnums.AttendanceCalendarDataType.WORK.getCode(), per.getDateType())).collect(Collectors.toList()).size()+""));

            attendanceMonths.add(attendanceMonth);
        }
        if (attendanceMonths.size() > 0){
            JpaUtil.save(attendanceMonths);
        }
        return Result.OK();
    }
}
